package com.coocaa.x.service.litepm;

import android.content.ComponentName;
import android.content.Context;
import android.os.Environment;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

import com.coocaa.x.framework.app.CoocaaService.AIDLInterface;
import com.coocaa.x.framework.data.JObject;
import com.coocaa.x.framework.utils.Android;
import com.coocaa.x.framework.utils.AsyncTask;
import com.coocaa.x.framework.utils.LogUtils;
import com.coocaa.x.framework.utils.PMUtils.PackageMoveLocation;
import com.coocaa.x.service.litepm.PkgManager.AppClearCacheListener;
import com.coocaa.x.service.litepm.PkgManager.AppInstallListener;
import com.coocaa.x.service.litepm.PkgManager.AppMoveListener;
import com.coocaa.x.service.litepm.PkgManager.AppUnInstallListener;
import com.coocaa.x.service.litepm.PkgManager.SpeedUpListener;
import com.coocaa.x.service.litepm.aidl.ILitePMClearCacheListener;
import com.coocaa.x.service.litepm.aidl.ILitePMInstallListener;
import com.coocaa.x.service.litepm.aidl.ILitePMMoveAppListener;
import com.coocaa.x.service.litepm.aidl.ILitePMService.Stub;
import com.coocaa.x.service.litepm.aidl.ILitePMSpeedUpListener;
import com.coocaa.x.service.litepm.aidl.ILitePMUninstallListener;
import com.coocaa.x.service.litepm.data.AppInfo;
import com.coocaa.x.service.litepm.data.InstallParams;
import com.skyworth.framework.skysdk.properties.SkyGeneralProperties;
import com.skyworth.framework.skysdk.util.SdCardChecker;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;


public class PMServiceStub extends Stub implements AppClearCacheListener,
        AppMoveListener, SpeedUpListener, AppInstallListener, AppUnInstallListener {

    private PkgManager pm = null;
    private Context mContext;
    private Vector<AIDLInterface<ILitePMInstallListener>> installListener = new Vector<AIDLInterface<ILitePMInstallListener>>();
    private Vector<AIDLInterface<ILitePMUninstallListener>> unInstallListener = new Vector<AIDLInterface<ILitePMUninstallListener>>();
    private Map<String, AIDLInterface<ILitePMMoveAppListener>> moveAppListener = new HashMap<String, AIDLInterface<ILitePMMoveAppListener>>();
    private Map<String, AIDLInterface<ILitePMClearCacheListener>> clearCacheListener = new HashMap<String, AIDLInterface<ILitePMClearCacheListener>>();
    private Vector<AIDLInterface<ILitePMSpeedUpListener>> speedUpListener = new Vector<AIDLInterface<ILitePMSpeedUpListener>>();

    public PMServiceStub(Context context) {
        mContext = context;
        PkgManager.create(mContext);
        pm = PkgManager.getInstance();
        pm.setInstallListener(this);
        pm.setunInstallListener(this);
        pm.setSpeedUpListener(this);
    }


    @Override
    public void whoAmI() {
        LogUtils.d("wai", "<<LitePMService>> who am i??  " + mContext.getPackageName());
    }

    @Override
    public void addInstallListener(ILitePMInstallListener arg0)
            throws RemoteException {
        // TODO Auto-generated method stub
        synchronized (installListener) {
            if (arg0 != null) {
                IBinder binder = arg0.asBinder();
                AIDLInterface<ILitePMInstallListener> i = new AIDLInterface<ILitePMInstallListener>(
                        binder, arg0);
                installListener.add(i);
            }
        }

    }

    @Override
    public void addUninstallListener(ILitePMUninstallListener arg0)
            throws RemoteException {
        // TODO Auto-generated method stub
        synchronized (unInstallListener) {
            if (arg0 != null) {
                IBinder binder = arg0.asBinder();
                AIDLInterface<ILitePMUninstallListener> i = new AIDLInterface<ILitePMUninstallListener>(
                        binder, arg0);
                unInstallListener.add(i);
            }
        }
    }

    @Override
    public void addSpeedUpListener(ILitePMSpeedUpListener arg0)
            throws RemoteException {
        // TODO Auto-generated method stub
        synchronized (speedUpListener) {
            if (arg0 != null) {
                IBinder binder = arg0.asBinder();
                AIDLInterface<ILitePMSpeedUpListener> i = new AIDLInterface<ILitePMSpeedUpListener>(
                        binder, arg0);
                speedUpListener.add(i);
            }
        }
    }

    @Override
    public boolean clearCache(String packageName, ILitePMClearCacheListener listener)
            throws RemoteException {
        // TODO Auto-generated method stub
        synchronized (clearCacheListener) {
            if (listener != null) {
                IBinder binder = listener.asBinder();
                AIDLInterface<ILitePMClearCacheListener> i = new AIDLInterface<ILitePMClearCacheListener>(
                        binder, listener);
                clearCacheListener.put(packageName, i);
            }
        }
        pm.clearCache(packageName, this);
        return true;
    }

    @Override
    public AppInfo getAppInfo(String pkgname) throws RemoteException {
        // TODO Auto-generated method stub
        return pm.getInstalledAppInfo(pkgname);
    }

    @Override
    public List<AppInfo> getInstalledApps() throws RemoteException {
        // TODO Auto-generated method stub
        return pm.getInstalledAppList();
    }

    @Override
    public void install(String apkfile, boolean silent, InstallParams params) throws RemoteException {
        // TODO Auto-generated method stub
        boolean value = SkyGeneralProperties.getBoolProperty("HIGH_MEMORY");
        boolean slient_install = SkyGeneralProperties.getBoolProperty("x_install_with_packageinstaller");
        if (slient_install)
            pm.install(apkfile, false, params);
        else
            pm.install(apkfile, value ? silent : false, params);
    }

    @Override
    public void installWithSP(String apkfile, InstallParams params) throws RemoteException {
        // TODO Auto-generated method stub
        pm.installWithSP(apkfile, params);
    }

    @Override
    public boolean isInstalled(String pkgname) throws RemoteException {
        // TODO Auto-generated method stub
        return pm.isAppInstalled(pkgname);
    }

    @Override
    public boolean killProcess(String pname) throws RemoteException {
        // TODO Auto-generated method stub
        pm.killProcess(pname);
        return true;
    }

    private static class MoveAppLogInfo extends JObject {
        public String pkgname, appname, versionname;
    }


    @Override
    public boolean movePackage(String packageName, String location,
                               ILitePMMoveAppListener listener) throws RemoteException {
        // TODO Auto-generated method stub
        synchronized (moveAppListener) {
            if (listener != null) {
                IBinder binder = listener.asBinder();
                AIDLInterface<ILitePMMoveAppListener> i = new AIDLInterface<ILitePMMoveAppListener>(
                        binder, listener);
                moveAppListener.put(packageName, i);
            }
        }
        PackageMoveLocation _location = PackageMoveLocation.valueOf(location);
        try {
            MoveAppLogInfo i = new MoveAppLogInfo();
            i.pkgname = packageName;
            i.appname = Android.getAppNameByPkg(packageName);
            i.versionname = Android.getVersionName(mContext, packageName);

            LogUtils.SubmitLog log = new LogUtils.SubmitLog(LogUtils.PRODUCTID_APPSTORE, "as2_move_app_onstart");
            switch (_location) {
                case EXTERNAL_MEDIA:
                    log.addParam("path", "0");
                    break;
                case INTERNAL_MEMORY:
                    log.addParam("path", "1");
                    break;
            }
            log.addParam("app", i.toJSONString());
            LogUtils.submit(log);
        } catch (Exception e) {
        }
        pm.movePackage(packageName, _location, this);
        return true;
    }

    @Override
    public void removeInstallListener(ILitePMInstallListener arg0)
            throws RemoteException {
        // TODO Auto-generated method stub
        synchronized (installListener) {
            if (arg0 != null) {
                IBinder binder = arg0.asBinder();
                for (AIDLInterface<ILitePMInstallListener> i : installListener) {
                    if (i.binder == binder) {
                        installListener.remove(i);
                        break;
                    }
                }
            }
        }
    }

    @Override
    public void removeUninstallListener(ILitePMUninstallListener arg0)
            throws RemoteException {
        // TODO Auto-generated method stub
        synchronized (unInstallListener) {
            if (arg0 != null) {
                IBinder binder = arg0.asBinder();
                for (AIDLInterface<ILitePMUninstallListener> i : unInstallListener) {
                    if (i.binder == binder) {
                        unInstallListener.remove(i);
                        break;
                    }
                }
            }
        }
    }

    @Override
    public void removeSpeedUpListener(ILitePMSpeedUpListener arg0)
            throws RemoteException {
        // TODO Auto-generated method stub
        synchronized (speedUpListener) {
            if (arg0 != null) {
                IBinder binder = arg0.asBinder();
                for (AIDLInterface<ILitePMSpeedUpListener> i : speedUpListener) {
                    if (i.binder == binder) {
                        speedUpListener.remove(i);
                        break;
                    }
                }
            }
        }
    }

    @Override
    public boolean speedUp(int delay)
            throws RemoteException {
        return pm.speedUp(delay);
    }

    @Override
    public boolean startApp(String clsName, boolean isRoot, String pkgname) throws RemoteException {
        if (pkgname == null)
            return false;
        LogUtils.d("startApp pkgname:" + pkgname+"; clsName:"+clsName+"; isRoot:"+isRoot);
        return pm.startApp(clsName, isRoot, pkgname);
    }

    @Override
    public boolean startAppByComponentName(String clsName, boolean isRoot, ComponentName component)
            throws RemoteException {
        LogUtils.d("startAppByComponentName cn:" + component+"; clsName:"+clsName+"; isRoot:"+isRoot);
        if (component == null)
            return false;
        return pm.startAppByComponentName(clsName, isRoot, component);
    }

    @Override
    public void uninstall(String pkgname, boolean silent) throws RemoteException {
        boolean value = SkyGeneralProperties.getBoolProperty("HIGH_MEMORY");
        pm.uninstall(pkgname, (value == true) ? silent : false);
    }

    private List<String> uninstallList = new ArrayList<String>();
    private String curPkg = "";

    @Override
    public void uninstallApps(List<String> pkgList,boolean needAdd)
    {
        LogUtils.d("un", "SERVICE uninstall uninstallAppList..NNN. " + pkgList.size()+"; "+uninstallList.size()+"; "+pkgList.get(0));
        synchronized (uninstallList) {
            List<String> tempList = null;
            if (needAdd && uninstallList != null && uninstallList.size() > 0) {
                tempList = new ArrayList<String>();
                tempList.addAll(uninstallList);
            }
            uninstallList = null;
            uninstallList = new ArrayList<String>();
            if (tempList != null)
                uninstallList.addAll(tempList);
            uninstallList.addAll(pkgList);
            LogUtils.d("un", "SERVICE  uninstall uninstallAppList...pkg:" + uninstallList.get(0) + "; " + uninstallList.size());
            pm.uninstall(uninstallList.get(0), true);
        }
    }

    @Override
    public List<String> getUninstallList()
    {
        LogUtils.d("un", "SERVICE  getUninstallList.00..uninstallList.size(): " + uninstallList.size());
        return uninstallList;
    }

    @Override
    public int getAppInstallState(String pkgname) throws RemoteException {
        return pm.getInstallState(pkgname);
    }


    @Override
    public void onUninstallStart(final AppInfo appInfo) {
        // TODO Auto-generated method stub
        curPkg = appInfo.pkgName;
        synchronized (unInstallListener) {
            for (final AIDLInterface<ILitePMUninstallListener> i : unInstallListener) {
                AsyncTask.runOnThread(new Runnable() {
                    @Override
                    public void run() {
                        // TODO Auto-generated method stub
                        try {
                            i.i.onUninstallStart(appInfo);
                        } catch (Exception e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                });
            }
        }
    }

    @Override
    public void onUninstallEnd(final AppInfo appInfo, final int result, final String extra) {
        // TODO Auto-generated method stub
        AsyncTask.runOnThread(new Runnable() {
            @Override
            public void run() {
                synchronized (unInstallListener) {
                    for (final AIDLInterface<ILitePMUninstallListener> i : unInstallListener) {

                        // TODO Auto-generated method stub
                        try {
                            i.i.onUninstallEnd(appInfo, result, extra);
                        } catch (Exception e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }

                    }
                }
                synchronized (uninstallList) {
                    LogUtils.d("un", "SERVICE onUninstallEnd   uninstallList.size():" + uninstallList.size());
                    if (uninstallList.size() > 0) {
                        if (uninstallList.contains(appInfo.pkgName)) {
                            uninstallList.remove(appInfo.pkgName);
                            LogUtils.d("un", "SERVICE onUninstallEnd uninstallAppList... " + uninstallList.size() + "; " + appInfo.pkgName);
                        } else {
                            boolean isAppInstalled = Android.isPackageInstalled(mContext, uninstallList.get(0));
                            if (!isAppInstalled)
                                uninstallList.remove(0);
                            LogUtils.d("un", "SERVICE  onUninstallEnd  the package is not in uninstallList");
                        }
                        if (uninstallList.size() > 0) {
                            try {
                                Thread.sleep(100);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            uninstallApps(uninstallList, false);
                        }
                    }
                }
            }
        });
    }

    @Override
    public void onInstallStart(final String apkfile, final AppInfo appInfo, final InstallParams params) {
        // TODO Auto-generated method stub
        synchronized (installListener) {
            for (final AIDLInterface<ILitePMInstallListener> i : installListener) {
                AsyncTask.runOnThread(new Runnable() {
                    @Override
                    public void run() {
                        // TODO Auto-generated method stub
                        try {
                            i.i.onInstallStart(apkfile, appInfo, params);
                        } catch (Exception e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                });
            }
        }
    }

    @Override
    public void onInstallEnd(final String apkfile, final AppInfo appInfo, final int result,
                             final String extra, final InstallParams params) {
        // TODO Auto-generated method stub
        synchronized (installListener) {
            for (final AIDLInterface<ILitePMInstallListener> i : installListener) {
                AsyncTask.runOnThread(new Runnable() {
                    @Override
                    public void run() {
                        // TODO Auto-generated method stub
                        try {
                            i.i.onInstallEnd(apkfile, appInfo, result, extra, params);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                });
            }
        }
    }

    @Override
    public void onSpeedUpStart(final int configDelay, final long free, final long total) {
        // TODO Auto-generated method stub
        synchronized (speedUpListener) {
            for (final AIDLInterface<ILitePMSpeedUpListener> i : speedUpListener) {
                AsyncTask.runOnThread(new Runnable() {
                    @Override
                    public void run() {
                        // TODO Auto-generated method stub
                        try {
                            i.i.onSpeedUpStart(configDelay, free, total);
                        } catch (Exception e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                }, true);
            }
        }
    }

    @Override
    public void onSpeedUpReallyKillEnd(final long free, final long total) {
        // TODO Auto-generated method stub
        synchronized (speedUpListener) {
            for (final AIDLInterface<ILitePMSpeedUpListener> i : speedUpListener) {
                AsyncTask.runOnThread(new Runnable() {
                    @Override
                    public void run() {
                        // TODO Auto-generated method stub
                        try {
                            i.i.onSpeedUpReallyKillEnd(free, total);
                        } catch (Exception e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                }, true);
            }
        }
    }

    @Override
    public void onSpeedUpEnd() {
        // TODO Auto-generated method stub

        synchronized (speedUpListener) {
            for (final AIDLInterface<ILitePMSpeedUpListener> i : speedUpListener) {
                AsyncTask.runOnThread(new Runnable() {
                    @Override
                    public void run() {
                        // TODO Auto-generated method stub
                        try {
                            i.i.onSpeedEnd();
                        } catch (Exception e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                }, true);
            }
        }
    }

    @Override
    public void onPackageMoved(String pname, PackageMoveLocation location,
                               boolean success) {
        // TODO Auto-generated method stub
        ILitePMMoveAppListener listener = null;
        synchronized (moveAppListener) {
            listener = moveAppListener.get(pname).i;
            moveAppListener.remove(pname);
        }

        if (listener != null) {
            try {
                listener.onPackageMoved(pname, location.toString(), success);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        try {
            MoveAppLogInfo i = new MoveAppLogInfo();
            i.pkgname = pname;
            i.appname = Android.getAppNameByPkg(pname);
            i.versionname = Android.getVersionName(mContext, pname);

            LogUtils.SubmitLog log = null;
            if (success)
                log = new LogUtils.SubmitLog(LogUtils.PRODUCTID_APPSTORE, "as2_move_app_onsuccess");
            else {
                log = new LogUtils.SubmitLog(LogUtils.PRODUCTID_APPSTORE, "as2_move_app_onfailed");
                if (SdCardChecker.isSDCardAvaiable()) // 只有sdcard存在的情况下才有这么个功能
                {
                    boolean isSDEmulated = Environment.isExternalStorageEmulated();
                    if (!isSDEmulated)
                        log.addParam("sdcard", "external");
                    else
                        log.addParam("sdcard", "virtual");
                } else {
                    log.addParam("sdcard", "none");
                }
            }
            switch (location) {
                case EXTERNAL_MEDIA:
                    log.addParam("path", "0");
                    break;
                case INTERNAL_MEMORY:
                    log.addParam("path", "1");
                    break;
            }
            log.addParam("app", i.toJSONString());
            LogUtils.submit(log);
        } catch (Exception e) {
        }
    }

    @Override
    public void onPackageCacheClear(String packageName, boolean success) {
        // TODO Auto-generated method stub
        ILitePMClearCacheListener listener = null;
        synchronized (clearCacheListener) {
            listener = clearCacheListener.get(packageName).i;
            clearCacheListener.remove(packageName);
        }

        if (listener != null)
            try {
                listener.onPackageCacheClear(packageName, success);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    }

}
